package md.specialEqp.type;

import graphql.schema.DataFetchingEnvironment;
import lombok.*;
import md.cm.geography.Adminunit;
import md.cm.unit.Unit;
import md.specialEqp.RegState_Enum;
import md.specialEqp.UseState_Enum;
import md.specialEqp.inspect.Detail;
import md.specialEqp.inspect.Isp;
import org.fjsei.yewu.filter.Node;
import org.fjsei.yewu.util.Tool;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.search.engine.backend.types.Aggregable;
import org.hibernate.search.engine.backend.types.Sortable;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.*;

import jakarta.persistence.*;
import java.time.LocalDate;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

import static jakarta.persistence.FetchType.LAZY;

/**管道单元,一条管道装置底下有很多的管道单元来组成的。
 * 每个单元管道特性表 TB_PIPELINE_UNIT_PARA JC_PIPELINE_UNIT_PARA JC_TEMP_PIPELINE_UNIT_PARA
 * 单元没有独立的地理定位字段，归属业务管辖区域码也没做独立设置；单元可能超长一百公里。
 * 同一个使用单位下的（工程装置名称、管道编号）不允许重复。
 * 管道单元无法独立生存！ 都是父辈对象的依附(一块砖), 脱离父辈对象的管道单元毫无意义。
 * 关键字段》》 Pipeline + "管道编号 code"; 默认的排序字段=code;
 * 实际上监察所管理的压力管道所指范围也仅仅是需要监督运行的重要部分，不是全部管子。单元划断依据也有不同的，可长可短的。
 * <压力管道数据表>是本模型的精简版List;
 * 单独一个的管道单元有没有 大修或改造的说法， 整个父对象的大修或改造，单独一个单元算啥---是一般地整改或维修 UseState_Enum=停用。
 * 本实体KEY标识之一code居然是用户自己编造，唯一性实际是使用单位用户维护。
 * oid=DA19340,仅仅出现在检验平台,两个平台都没有任何管道单元！
 * EQP_CODE, START_PLACE, END_PLACE, BOX_NAME + rno ==唯一性
 */

//@Table( uniqueConstraints = {@UniqueConstraint(columnNames={"pipe_id", "rno"})} )
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Entity
@Builder(toBuilder=true)
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region = "Medium")
@Indexed
//@Table(indexes={@Index(columnList = "det_id",unique=false),})改成多对多了!
public class PipingUnit implements Node {
    /*@Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "commonSeq")
    @SequenceGenerator(name = "commonSeq", initialValue = 1, allocationSize = 1, sequenceName = "SEQUENCE_COMMON")
    protected Long id;*/

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private UUID id;

    //在PipingUnit索引里面Pipeline直接映射它的UUID；但是要是别的索引关联了PipingUnit实体模型，这个注解该怎么办？又不能单独的设定注解目的。
    /**单元很多有几百个： 脱离设备台账Eqp大表; EqpEs也无法支撑,ES搜索失效。
     * 非空字段！    最多单元是3505D2591,DC02591；
     * 对于同一个管道装置的下挂的多单元：监察给出的指定分配的负责的检验机构最好是只能唯一个机构。
     * 搜索索引：若要对该这嵌套实体ID能可统计排序的话，就必须自定义桥接，或者干脆Eqp.id定义出独立Keyword?
     * [目标修订]把PipLine.useu.company|person.name直接放入ES索引以便直接可搜索单位名称，避免两次接力搜索法模式出现。
     * IndexedEmbedded 和 @PropertyBinding同时加会报错 Duplicate index field definition: 'pipe';
     * 直接加@IndexedEmbedded(includeEmbeddedObjectId=true,includePaths={"id","useu"} )，定义文件还是Object-同步报错!
     * */
    //@InvoiceLineItemsSummaryBinding
    //@KeywordField(valueBridge = @ValueBridgeRef(type = PipelineValueBridge.class) )

//    @PropertyBinding(binder = @PropertyBinderRef(type = NodeIdBinder.class))
    @IndexedEmbedded(includeEmbeddedObjectId=true,includePaths={"id","useu.id","useu.company.name","useu.person.name"} )
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "pipe_id")
    private Pipeline  pipe;

    //@ElementCollection：无法给其它实体用，是依附于主表的， Set<字段类型>是非实体 Set（@Embedded或基本数据类型）


    /**EQP_CODE管道编号: 默认的排序字段，可能有好几百个的管道单元，排序方便人工查找。
     * 管道单元编号+使用单位{.id}==唯一识别关键字组合。     注意：还是code作为唯一性关键字最为恰当！！
     * 【使用单位】:罗源安然管道燃气有限公司,【管道编号】：LY-FSZ-LuoY-20XJ-11-2-02-1不存在！
     【用户编名字】使用单位自主制定的 管道编号。 这号随意性强；有长有短的编码： ‘LS1-5101-100-C3B’  ‘ZQ3’，针对单位内部code才唯一。
     * 每个单元编码不同，管道单元的代码：报告书和单线图里面的key。
     * 同一个使用单位下的同一工程装置名称、管道编号不允许重复。
     ??搜索过滤： Pipeline pipe必须首先敲定吧， pipe底下顶多1000条PipingUnit，数据都发给了再在前端也能简单搞定需求。
     ?琢磨有没有业务需求？ Pipeline不能事先确定的？过滤： 根据管道单元登记编号 反过来 要求过滤出来Eqp? 而Elasticsearch无法关联多表查询。
     pipe同一个EQP_CODE='石狮食锦记天然气管道'有很多个，注销状态的； {"pipe_id", "code"}无法保障唯一。
     监察平台最多2262条单元，检验最多4522条单元
     ES搜索不能搜索少于3个有效字符的，必须精确查的，就要增加 _sort 字段来配套！
     ngram_analyzer底层配置文件引入pcode_tokenizer定义以后code_sort没啥用？ 保留当作code的排序聚合用途。
     * */
    @FullTextField(analyzer = "ngram_analyzer")         //改pcode_tokenizer后，已经支持任意字符串的搜索
    @KeywordField(name ="code_sort", sortable=Sortable.YES)
    private String  code;


    /**多个检验机构同时存在业务的： @本字段还没有实际使用?从单元关联检验？的需求吗。反过来的@注意计费里面又有另外配置单元的字段不能替代本字段。
     * 每个管道单元在本平台只能存在唯一一个活动的Task{【局限性】排斥多业务并行，必须前面任务终结后面才能受理，尽量缩短排除锁定时间跨度界线}。
    当前管道单元最新已生成task关联关系表[任务锁],直接在PipingUnit增设'当前task'=业务锁；
     业务锁困扰: 特殊任务可以不指定单元没有在任务单声明每一个PipingUnit只需要Eqp代指(实际报告或证明书可以另外约束指定详细单元=根本没有排他锁)，
     再不行只能多加个业务锁了,分类别加锁。 目前思路针对监管 #核心业务# 上锁【主锁 task】。
     检验业务可能分包：无损检测等，不一定都是检验单位自己干活的；分开的子报告如何合并管理(不是本检验机构的外部人员署名签字的分项报告/加盖公章)。
     ? isp1,isp2[.task.流转状态];替代吗 ? #isp1,isp2指代的是专门给监察平台看的已经完成的检验，并非实时操作。
     1个task底下也能分拆出多个Isp: 原始记录输入选择的是否可以再次挑选到底归属哪一个具体isp亦即报告号的去编制的【管道单元太多了可拆分为多个isp报告】。
     全面检验和年度在线检验可能同一时间撞见吗，task锁定：装置task/Isp派工干脆不选择管道单元，后续收费计算和报告原始记录的输入选择单元时刻酌情挑选：提示task锁定:避免重复包罗单元。
     *真正的单元配置选择实际在收费计算环节挑选的：选完了才能够计算收费；可能原始记录编制时间还要提早点。最后才能确认收费。
     * 本字段设置时机：出报告前派工时刻专门有个环节配置这个det=?，(收费确认后)报告流转终结之后就可能算业务锁释放时机设置 det=null。
     * 【问题】同一时间不允许对一个管道单元有两次检验一起进行中(未结束的)。
     *ES索引， HS考虑： [id1, id2,] 非对象的List多对多，实现id过滤，性能和同步即时性问题。 去掉没法依照本字段进行过滤！
     * todo:// 快速搜索用途：：是否已经在当前业务当中了，前端也可能自主js Set[]判定？  $PipingUnit这个ES索引还没有利用起来的
     * todo: 还没有代码来设置本字段，中间JPA关联表以及pipingUnit ES索引自然就没数据。
    */
    @IndexedEmbedded(includePaths = {"id"} )
    //@PropertyBinding(binder = @PropertyBinderRef(type = NodeIdBinder.class)) 临时看看：todo：//性能
    @Builder.Default
    @ManyToMany(mappedBy = "pipus")
    private List<Detail>  dets= new LinkedList<>();
//    @ManyToOne(fetch= FetchType.LAZY)
//    @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.SHALLOW)    //辅助工程报错才加
//    private Detail  det; 改多对多@！

    //private Task task;     //单向关联关系，就是锁定占坑的。 但是模型Eqp.Task字段是不存在的{eqp.isp.task才是}。

    //1"序号（监管平台生成）" ?系统内部id?排序的;
    /**管道单元注册登记编码  管道单元登记编号 EQP_UNT_REGCOD 来自监察平台的！；
     * 注册登记号+监管机构{.id}==唯一识别关键字组合。
     * 多数是顺序编号编下去: 总使用证-1,-2,-3...。
     * [new PipingUnit(), 新增加] rno ust 自动； ++ 注册时间??
     * 父辈管道对象也有 大的  注册登记代码; 这个编码等同=OIDNO+后缀数字(顺序号)？？=无意义。也有合并多个装置的情形。
     * USE_STA=7\8垃圾(必须过滤掉) 可以保证唯一，但是可能是null;  EQP_UNT_REGCOD!=null可以保证oid/cod+的唯一性。
     EQP_UNT_REGCOD=null的，同步时刻{EQP_CODE,START_PLACE,END_PLACE,BOX_NAME}组合认定为同一条。EQP_UNT_REGCOD非空的可以单独做关键字。
     组合才能确认一条单元;@不能有两条{EQP_CODE,START_PLACE,END_PLACE,BOX_NAME}+EQP_UNT_REGCOD=null;#
     检验平台看到的EQP_UNT_REGCOD有可能在监察平台却没找到。  EQP_UNT_REGCOD必须是来自监察平台的数据，同一条rno基本字段以监察为准。
     【管道特别】某个使用单位底下的所有管道实际上都只有一个注册证书，eqp.reg实际只能算一个总闸？没有区分哪一个管道装置,任务分派特殊。
     */
    @KeywordField(sortable=Sortable.YES)
    private String  rno;

    /** BOX_NAME 管道单元名称；  给用户识别的名字（=?设备型?） 可重复。 设计资料上的管道名称；
     * 【上传国家平台】似乎用这个名称做关键字的？但是旧平台不是这个用途含义的；将来可能归并用途？：估计需要name + 使用单位{.id}==当作唯一性组合使用。还是仅仅对于上传国家平台临时转换？
     * 目前上传国家平台“管道名称”对方概念的实际上传内容= 工程名称？+rno；#和我方旧平台name的概念不一样。$@多余@@，还是强制本平台统一关键字组合:code+单位{父辈装置cod}来定位唯一性;
     * 管道名称(登记单元)  管道名称(工程名称)： 实际每条单元可不同、也可相同。 是有些是照抄父设备eqp.titl但是不是全都这样。
     * 使用单位已经自主制定的直接用！  设计资料上的管道名称；用工程编号代替也行的。
     * 【！字段同名混乱】了！ BOX_NAME本应该是父辈使用的； 管道名称(工程名称) ：有可能相同的。
     * 另外还有易混淆的： PROJ_NAME 工程名称：{工程名称可能直接用父设备的设备名字eqp.titl 随意!}
     * ？没必要可搜索的； 分辨度差异性太小了。
     * 长输管道在上传国家平台的情况：管道单元名称=管道名称+rno；
     */
    private String  name;

    //为止点起点地理定位,经度纬度？没意义，实际业务都要查设计图，找使用单位查更加明细资料来做地理定位。
    //直接套用管道设备的Address　pos字段定位地理，以及归属业务管辖的区域码{单个管道设备一个业务唯一管理部门/出报告方便}。

    /**管道起点START_PLACE; 看单线图{设计单位}和工程图{安装单位}
     * 起点（站名）
     * 图纸上的标签代码,甚至是内部定位叙述，不特定指代
     */
    @FullTextField
    private String  start;

    /**管道止点END_PLACE; 看单线图和工程图
     * 终点（站名）
     * 图纸上的标签代码,甚至是内部定位叙述，不特定指代
     */
    @FullTextField
    private String  stop;

    /**使用状态USE_STA；若1,2,3,9是有效管理的。每个单元都独立的状态；
     * 1未投用2在用3停用9在用未注册登记;  4报废5拆除 =7\8垃圾(必须过滤掉), 使用状态和监察注册有一点关系；6迁出=变更监察省份；
     *注册状态是行政上发证书的{要收钱拿证}， 使用状态是微细管理业务停顿{不收钱报停复工}；
     * [9在用未注册]就是还没有分配注册码 rno;
     * 追溯？关联的日志。？？应该关联log审核流水对象。 USE_STA: "2"
     管道？不一致：采信那个状态； 在检验=7垃圾数据 但是 监察显示是在用的。
     */
    @GenericField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    @Enumerated
    private UseState_Enum  ust;

    //TB_PIPELINE_UNIT_PARA.EQP_REG_STA  '注册状态'
    //TB_PIPELINE_UNIT_PARA.EQP_REG_COD '注册代码' 都是重复:"管20闽E0307(18)-1" 一个企业一个号码;
    //TB_PIPELINE_UNIT_PARA.REG_UNT_ID '注册机构'   [特殊！]：管道不能移动转交,管道单元无法独立生存！都是一次性数据。
    /**注册EQP_REG_STA，监察知道吗　[{id:'0',text:'待注册'},{id:'1',text:'在册'},{id:'3',text:'注销登记'}];
     * 每个单元都独立的注册，当前管道设备底下的各个管道单元实际地址和管理区域码不一定都一样的。
     * 当前每个管道设备底下的各个管道单元都是同一个注册机构注册的。
     * 所属管道的父类Eqp.regu注册机构，注册发证的。管道单元没有迁出的/流动设备，责任监察机构就=注册机构;
     * 市场化的检验竞争，以整个管道装置设备oid/使用证、工程（装置）名称，统一划归某个检验机构。
     * 管道设备 没有移装的说法！ 管道单元是一次性筷子那样的。 [结论] 不需要独立设置注册状态, ust字段就够用了。
     * 注册时间??
     * EQP_REG_STA_NAME   REG_DATE1     注册行为记录 批准通过log 日期？
     * EQP_REG_STA=3&& ust==5表示没用数据？？  EQP_REG_STA
     */
    @GenericField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    @Enumerated
    private RegState_Enum  reg;
    /**注册代码生成批准行为日期 ，方便定位历史操作 关联的日志。？？应该关联log审核流水对象。REG_DATE
    * */
    private LocalDate regd;

    /**PROJ_NAME 工程名称：{设计概念,安装分期的} 同一个父辈对象底下的  工程名称 允许不一样。 PROJ_NAME
     * 一个@Eqp.父辈 装置名称@ 的底下允许多个工程名称;   '福建天辰耀隆20万吨/年己内酰胺技术改造项目'
     * 没必要做可搜索的字段？；
     * */
    private String  proj;

    //TB_PIPELINE_UNIT_PARA.UNIT_AREA_COD '管道单元所在区域'，设置上级管道设备的区域/大的包含小的地理区域码。
    //管道合并操作重新配置地址区域码Address pos设备登记位置;　注册监察机构的机构位置的区域码。

    /**.V_PIPELINE_DIA 监察没有字段，'计费用-管道直径（公称直径mm）规范，按照直径大小的区间来计费
     * 　数据较少;
     * 计费用-管道直径，NOMINAL_DIA公称直径（mm）； 不规范φ114.3　φ168，￠57, 168.3/114.3 有很多数据。
     * 计费依据：NOMINAL_DIA>=50.0&&NOMINAL_DIA<=150.0  + length;
     * 公称直径(mm); 若是存在多种规格，只填写典型管径数据{壁厚/直径};
     * 监察字段=NOMINAL_DIA "60.3/88.9" "168.3/273.1" "φ219" "114.3/168.3/219.1"    ??大概估算一个中间数字。
     */
    private Float dia;
    /**NOMINAL_PLY 公称壁厚(mm); 若是存在多种规格，只填写典型管径数据{壁厚/直径};
     *"Ф88.9*11.1"  "6.35/7.11"  "6.02/Φ60.3×3.91/Φ88.9×5.49"
     * 【特别注意】字段数据类型修改之后，实际在数据库还是旧的类型float，导致报错！
     * */
    private String thik;

    /**管道长度(m) LENGTH; 旧数据可null,可能超长一百多公里{这么长也不拆解开}。
     * 管道规格泛指的3个参数："公称直径(mm)"	"公称壁厚(mm)""管道长度(m)"
     * 管道规格必须填写数值型， 长度是本逻辑管道单元的合计数。 没必要用 Double型,精度足够;
     */
    private Float leng;

    //"管道级别"级别enum ?  .V_PIPELINE_LEVEL  '计费用-管道级别（[G][A-D][1-3]）'
    /**计费用-管道级别V_PIPELINE_LEVEL 监察没有字段：管道的各个所属单元都可有自己单独设置的级别。
     * const 管道级别=['GA1','GA2','GB1','GB2','GC1','GC2','GC3','GD1','GD2']; 有异常取值和"";
     * 监察 PIPELINE_LEVEL;
     * TB_PIPELINE_UNIT_PARA.PIPELINE_LEVEL'管道级别'　.V_PIPELINE_LEVEL'计费用-管道级别（[G][A-D][1-3]）'
     * G+ ABCD行业属性 +危险等级123；PIPELINE_LEVEL = "";　规范化用V_PIPELINE_LEVEL
     GA类(长输管道);  sort='81'
     GD类(动力管道) ; sort='83' && vart='832'
     GB类(公用管道);  sort='82'
     GC类(工业管道);  sort='83' && vart!='832'  ;    GC3是最安全和收费最便宜的。
     上传国家平台的级别需要映射转换：长输管道 pk 燃气管道的不一样。
     */
    @GenericField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    private String level;


    /**V_LAY_MODE 监察没有字段：计费用-敷设方式，TB_PIPELINE_UNIT_PARA.LAY_MODE   is '敷设方式' 随意填写　不规范
     *TB_PIPELINE_UNIT_PARA.V_LAY_MODE  is '计费用-敷设方式（架空、埋地、其他）'　Enum?比较少
     * LAY_MODE管道敷设方式[{id:'埋地',text:'埋地'},{id:'架空',text:'架空'},{id:'其它',text:'其它'}]
     计费"LAY_MODE=!埋地||LAY_MODE=!架空"   "架空、埋地压力管道，收费标准上浮10%"
     *实际上 V_LAY_MODE还是填写 不规范。对比LAY_MODE感觉没啥变化
     *前端规范后: const 管道敷设式=['埋地','架空','埋地+架空','无','其它']+""+null;
     */
    private String  lay;

    /**计费用 管道材质 管道材料： "V_PIPELINE_MEDIUM", 监察没有字段： "计费用-管道材料（钢制/PE管）"
     * const 计费管材料=['钢制','PE管'];  钢制  PE管  null  ""
     * "172694", "钢制" ; "47207",  "PE管"
     * 计费不是字段 PIPELINE_MEDIUM ：管道材质，复合字段PIPELINE_MEDIUM材质代码,V_PIPELINE_MEDIUM材质大类，
     * 实际上　是标号 PE100;   20（GB/T8163-2008）
     * 计费依据：    PIPELINE_MEDIUM==钢制&&PIPELINE_LEVEL=!GA
     *监察字段=PIPELINE_MEDIUM；"PE100" "PE80" "Pe80 SDR11" "20（GB/T8163-2008）" "304/304L" "A333 GR.6" "06Cr19Ni10↵（GB/T14976-2012)" "Q345B"
     另外字段 "PIPELINE_DATUM_SIGN","管子材料牌号@0" 实际数据很少，应该替换成PIPELINE_MEDIUM。
     ？可搜索字段就没必要， 没迫切需求，流处理统计另外设置系统跟随数据源。
     */
    private String  matr;

    /**介质 SEND_MEDIUM 数据质量更好点？两个字段感觉差不多，冗余字段？？
     * 设计介质 SEND_MEDIUM "输送介质"
     * 对比 字段 WORK_MEDIUM 数据空的太多了；
     */
    private String  mdi;


    //关联 备份字段：
    /**下次年检日期 YEAR_NEXT_ISP_DATE；  下次年检日期： 一年一次的；
     * 年检的？定检的？下次检验日：：是交叉进行的吗。 还是都能组合认定日期的，2个日期一起改，改哪一个，年检的？定检的？？
     * 在线检验一般以宏观检查和安全保护装置检验为主，必要时进行测厚检查和电阻值测量。管道的下述部位一般为重点检查部位：
     * */
    @GenericField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    private LocalDate nxtd1;      //NEXT_ISP_DATE1下次检验日期1（在线、年度）粗的检

    /**NEXT_ISP_DATE, "定期检验 下次检验日期"
     * 定检下检日期NEXT_ISP_DATE； 定检下检日期： 全面检验=停机下做的：（+压力试验）
     * 安全状况等级为1、2的是六年才一次的；  安全状况等级=3的是三年一次； 首次检验周期需缩短。
     * NEXT_ISP_DATE 定期检验下次检验日期 : 预定
     * */
    @GenericField(sortable=Sortable.YES,  aggregable=Aggregable.YES)
    private LocalDate nxtd2;      //NEXT_ISP_DATE2下次检验日期2(机电定检，内检，全面）

    /**INCP_NEXT_ISP_DATE
     * 监检报告下检日期： 难道特别？ 监检报告下检日期： (管道元件)制造监检,施工监检(安装/改造/大修)； 下检日期肯定不是监检性质的业务。
     * 为何有?监检报告下检日期INCP_NEXT_ISP_DATE； 含义等价于{监检报告已经标注的}下一次的定期检验开始日期吗？
     * 对于还没有做定检的才是【实际数据等价于】定检下检日期：。
     * 注册生成必须有监检报告下检日期，若新注册敲定了定检下检日期：不是新注册的已经有定检的例外处理，要看定检报告的结论。
     * 监检报告下检日期：敲定的到底给谁用！？ 改造大修之后的监察（监检报告提交给监察人员审核）重新修正状态确认：选择下次检验日期以及到底是年检的还是定检的下次检验日。
     * */
    //private Date nxtd0; 【不需要单独再设置监检下检日】  =定检下检日期  OR= 下次年检日期?
    /*下次检测日 , 用于检测的管理
     * */
    //private LocalDate nxttd;

    /**监察扩展，JSON非结构化存储模式的参数，能支持很多个，但是java无法简单化访问或操控单个技术参数。
     * 单线图URL;
     * 【单线图为何不能放入技术参数中】多次检验报告同一个管道单元单线图可能修改过，用户端修改的，修改权限不受控制，工程设计变动的。
     *  1，主要还是监察人员对于单线图根本没兴趣看吧； 2，使用单位要自己改动图片啊(更新)。
     *注解@Lob 默认是 text 物理数据库类型。针对底层CRDB数据库@Column改成"jsonb"；
     */
    @Lob
    @Basic(fetch= FetchType.LAZY)
    @Column( columnDefinition="jsonb")
    private String  svp;
    /*
    管道规格 PIPELINE_SPEC
    设计压力MPa：DESIGN_PRESS
    对接焊口数量：HK_NUM
    图号： PIC_NO  ？？等同单线图吗?
    @ 监检报告下检日期： 【保留】； 监检报告下检日期 INCP_NEXT_ISP_DATE
    监检日期：[可能是个范围值， 开始日 --- 结束日]
    监检报告编号： INCP_ISP_REPORT_COD
    监检结论： INCP_ISP_CONCLU  ?结论还有分好多种的，不是绝对的 YES,NO就可以。若是NO就没法通过，没通过如何能进入下一步注册登记啊?
    监检报告编号：  监检报告下检日期：  监检结论：
    * */

    /**扩展的技术参数，JSON非结构化存储模式的参数
     * 权限控制 类比Eqp.pa的模式；
     * 离线快照， 非实时关联的。
     * 设计/工作条件一共5个参数： "设计压力(MPa)"	"工作压力(MPa)"	"设计温度(℃)"	"工作温度(℃)"	介质；
     * 长输管道的上传管家平台增加字段？ @ 定期检验方式（内检测/外检测/内外检测）：来自Detail的配置字段吗？
     * 长输管道的上传管家平台增加字段？ @ 无损检测机构名称  ？：来自Detail的
     * 长输管道的上传管家平台增加字段？ @ 管道是否具备内检测条件   ？pa.{}
     */
    @Lob
    @Basic(fetch= FetchType.LAZY)
    @Column( columnDefinition="jsonb")
    private String  pa;
    /*
    工作压力MPa：WORK_PRESS
    试验压力：TRY_PRESS
    实际使用时间：USE_TIME
    绝热层材料：ADIABATIC_MEDIUM
    绝热层厚度：ADIABATIC_PLY
    安全保护装置数量：SAFE_MEC_NUM
    管子材料： PIPELINE_DATUM_SIGN
    备注： MEMO
    单线图直接在报告中体现，设备台账中不需要单线图。
    * */


/*  每一个单元可独立配置的：
	EQP_INST_DATE 安装日期
	第二页：管道基本信息汇总表
    INCP_ISP_REPORT_COD 监督检验报告号, 关联Isp;
    INCP_ISP_NAME 监督检验机构 关联ID;
    INCP_ISP_DATE 监检日期
    INCP_ISP_CONCLU 监督检验结论
    ISP_UNT_NAME 定检机构 ;?应该分配定检机构=管道装置统一敲定一个定检机构的-不能肢解了。
    ISP_REPORT_COD 定检报告号, 关联Isp;
    ISP_DATE 定期检验检验日期
    ISP_CONCLU 定期检验检验结论
    "设计压力(MPa)"	"工作压力(MPa)"	"设计温度(℃)"	"工作温度(℃)"
    单线图 :?一张图上面包含多个的管道单元了[无需要复制多份的图片]； 或者相反， 一个管道单元需要很多张图纸来拼接的大图。
    单线图每份报告都要复制一份，原因是报告展示的是历史数据，单线图再次可能修改。
*/


    /**DESIGN_UNIT 设计单位  ；不会是个人； 合770公司名；
     * "德国" "TUNTEX DISTINCT CORP" "自设计"  "SEI"; "华润(南京)市政设计有限公司" "华润（南京）市政设计有限公司"
     * */
    @ManyToOne(fetch= FetchType.LAZY)
    @JoinColumn
    private Unit desu;

    /**INST_UNIT 安装单位， 不会是个人‘Person’的； 合计1100家公司名；
     *"不明" '/' "二公司" "核23公司" "核二三公司" "省安" "冶建" "中石化第十建设有限公司"
    #应对可能出现的特别需求： 搜索过滤目的， 突发需求搜索， 突发业务需求的统计过滤, SQL数据库(不通过通常用途的Elasticsearch)。
     * */
    @ManyToOne(fetch= FetchType.LAZY)
    @JoinColumn
    private Unit insu;

    /**EQP_FINMAKE_DATE 投用日期 ，超期服役？ 影响到结论的！改造大修
     * 不能直接用Instant类型 : "1971-02-04T21:52:30Z"  Instant是时间整数量=等同是long64的。
     * ZonedDateTime 类型：输入要求整数; 输出却是"2040-10-23T09:18:10+08:00[Asia/Shanghai]" ;国际化时间输入要求的?
     * 若用ZonedDateTime可以，但前端 input type='datetime' 处理只能当作文本，浏览器无法点击时区选择。
     * MySql物理存储字节数不一样，精确需要代价。
     * */
    private LocalDate used;
    /**安装日期,年月 EQP_INST_DATE; 工程牵扯纠纷查询用
     * */
    private LocalDate insd;

    /*单元所在区域：监察字段 EQP_AREA_COD,检验字段 UNIT_AREA_COD；管道单元的行政管理管辖区的依据？【长输管道一般就一条单元啊】；
     * 工业管道和动力管道又是聚集很小地域内的。 就剩公用管道：一般都是工程划分的{能够分离跑多远啊}。
     * */
    /**单元的 地理定位。长输管道覆盖范围大的情形特指核心地点
     * 目前没有数据，旧平台  UNIT_AREA_COD 单元所在区域：
     * 真没必要设置独立可搜索字段？
     * */
    @ManyToOne(fetch= FetchType.LAZY)
    private Adminunit ad;       //行政区划; 跨越区县的长输管道单元 归属监察行政级别。

    /*NOTELIGIBLE_FALG1 不合格标志1 （在线、年度，外检）; ? ? 没有单独针对单元的？？
     * 管道单元 是特例： 出现不合格的事情，必然要复检等待 ， 父辈的Eqp对象一整个都是复检不合格？？
     * */
    //private Boolean unqf1;

    /*检验的历史报告：
     * 旧平台或者外部来源的报告甚至手工报告； 自动构建一个Isp伪记录。
     * */
    //private Set<Isp> isps;   没有必要性！ 单元上面是Eqp就够了; pipe.isps<>;管道装置的，非针对单一个的单元。

    /**年度在线 年检 最近一次的检验记录 （在线） : 给监察看的。
     * 一个Isp:关联了多个的PipingUnit; 带来的特殊性！
     *若是@OneToOne(cascade = CascadeType.ALL)的:删除管道单元时刻会直接把Isp甚至isp_men_关联直接一起删除掉。所以修改关联关系改成多对一ManyToOne才是符合实际业务报告数据情况啊！
     *而OneToMany List<>正好相反的也能不做双向关系设定的。实际上可能多对多的关系，也能配置成一对一。
     * [若删除某个Isp]就需要针对isp1,isp2,ispsv都搜索一遍。
     * 对法Isp也没有声明@OneToMany(mappedBy = "")三个字段啊；  只能依赖Isp.Detail。在延伸依赖private Detail  det 业务锁;来关联查询过滤的。只能针对最新的业务过滤。
     * PipingUnit.det是最新的，不能代表说isp1==PipingUnit.det.isp成立的; 【特殊】这里的isp1/2/sv:是监察人员视角的状态数据。
     * 若不加fetch= LAZY,在ES索引重建时刻会多查关联join表数据，没用到的查了多余。
     * */
    @ManyToOne(fetch= LAZY,cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH,CascadeType.DETACH})
    @JoinColumn( referencedColumnName = "ID")
    private Isp  isp1;
    /**定期检验 最近一次的检验记录 (全面检验） : 给监察看的。
     * 这里 @OneToOne 对应的对方实体模型 根本不需要注解的。Isp本身应该关联的是Eqp(Pipeline)实体，也不是PipingUnit管道单元实体啊。
     * 这是 绝对的单方面 彻底单向做的关系模型！
     # 看着像需要@ManyToMany的，这里实际只需要多对一就可以。附属本管道单元的新一次Isp已设定完成，那么旧的Isp也不需要关联本管道单元了，
     * 历史检验报告数据Isp.pipeunits[]关联=就算丢失了：只能从报告Report.data{[]}内部非结构化数据提取寻找到底做了哪一些管道单元;  @[问题]？退化的关系@。
     * */
    @ManyToOne(fetch= LAZY,cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH,CascadeType.DETACH})
    @JoinColumn( referencedColumnName = "ID")
    private Isp  isp2;
    //  private Isp isp;   //定检检验报告
    //private Isp year;  //年检报告
    //监检报告， 同样一个管道装置的，安装 监检报告也可不一样。
    /**监检报告 {最近一次的} 记录;   改造大修也算监检  : 给监察看的。
     * 单方向维护：实际上可能多对多的关联@ManyToMany的。
     ？?若做成 @ManyToMany 的合并字段：List<Isp> ispmains; 三种类别Isp各选择一个已经终结的时间上最新的哪一个，合计只选取3个Isp[0,1,2] 其余删除吗。
     # 或者GraphQL模型接口上面自定义新的转义字段来映射：会多一层SQL查询;但是后端自己代码不能利用这个接口方法。
     * */
    @ManyToOne(fetch= LAZY,cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH,CascadeType.DETACH})
    @JoinColumn( referencedColumnName = "ID")
    private Isp  ispsv;

    /**安全状况等级 SAFE_LEVEL： 1 2级、3 4； 下结论：下检日期的决定因素。
     * 可对照！Eqp模型类似的有.cpa=事故隐患类别 ACCI_TYPE，
     * "2级"     安全状况等级：SAFE_LEVEL       ?检验的结论评定：？？
     * 容易混淆的  来自监察的-安全评定等级= SAFE_LEV；  而 SAFE_LEVEL 是管道单元的特有字段 。
     * "Ⅰ级" "一级" "Ⅲ级" "3" "3级" "未定级" 给人看的=太随意？ ；实际数据=null的太多;
     */
    private String safe;
    /**监察平台中没有看见 该单元！； 同步数据仅仅来自旧检验平台
     * 仅仅来自旧检验平台 监察没有该单元
     * ？为何需要该字段设置： Eqp设备也会目录外的，监察那一边根本没有该单元数据？。目的提示检验员的单元数据：检验平台监察平台 不一致；？未注册使用状态？根本没有物理数据。
     * */
    private Boolean  ninsp;

    /**对于可能被非结构化json关联本对象的模型@ ，必须保证本对象生存期超过1天时间，免于同一天内的相同id出现。
     * 删除对象【注意】确保crDate不是今天也即1天以上的才能Delete掉。
     * 为了非结构化json关联本对象而设置的；杜绝重复id碰撞，针对生存期超过一天的对象的。
     * */
    @GenericField
    @Builder.Default
    @Column(updatable = false)
    private LocalDate  crDate= LocalDate.now();

    //Relay的全局性的ID保证,和Java后端逻辑无关联，只是graphQL/Relay接口用的。
    public String getId(DataFetchingEnvironment env) {
        return Tool.toGlobalId(this.getClass().getSimpleName(), this.id);
    }

}


//不可改参数：管道编号EQP_CODE; 管道长度LENGTH;管道起点START_PLACE;管道止点END_PLACE;管道单元登记编号EQP_UNT_REGCOD;
//附带不可改属性： 使用状态USE_STA； 下次年检日期YEAR_NEXT_ISP_DATE；定检下检日期NEXT_ISP_DATE；监检报告下检日期INCP_NEXT_ISP_DATE；
// 年检报告编号YEAR_ISP_REPORT_COD； 年检结论YEAR_ISP_CONCLU；　年检日期YEAR_ISP_DATE；
//   定检检验报告编号ISP_REPORT_COD；　定检结论ISP_CONCLU；　定检日期ISP_DATE；
//   监检报告编号INCP_ISP_REPORT_COD；　监检结论INCP_ISP_CONCLU；　监检日期INCP_ISP_DATE；

//NOMINAL_DIA>=50.0&&NOMINAL_DIA<=150.0  + length;
//单项管道检验总长度;  LAY_MODE=!埋地||LAY_MODE=!架空     //PIPELINE_MEDIUM==钢制&&PIPELINE_LEVEL=!GA
/*
管道的分类、级别及界别划分http://xinzhi.wenda.so.com/a/1511970916201369
GA类(长输管道)又分为：GA1类、GA2类；
GB类(公用管道)又分为：GB1类、GB2类；
GC类(工业管道)又分为：GC1类、GC2类、GC3类；工业管道=是指企业、事业单位所属的;
GD类(动力管道) 又分为：GD1类、GD2类。 动力管道=火力发电厂用于输送蒸汽、汽水两相介质的管道
TB_PIPELINE_UNIT_PARA.IS_KX'是否为跨县区管道登记单元：0-否，1-是' 实际数据没有=1的。
单个管道设备底下再做细分的跨越区域登记管理一个管道单元有何意义？？登记管理区域实际上还能够升级地区级别的，还怕分解不了吗!
长输管道完全可以直接肢解成各个大地区独立的管道设备去搞登记的。
设计/工作条件一共5个参数： "设计压力(MPa)"	"工作压力(MPa)"	"设计温度(℃)"	"工作温度(℃)"	介质；
*/


/* @数据库修改脚本：
CREATE INDEX pipingunit_pipe_id_index ON public.pipingunit USING btree (pipe_id ASC);
CREATE INDEX pipingunit_isp1_id_index ON public.pipingunit USING btree (isp1_id ASC);
CREATE INDEX pipingunit_isp2_id_index ON public.pipingunit USING btree (isp2_id ASC);
CREATE INDEX pipingunit_ispsv_id_index ON public.pipingunit USING btree (ispsv_id ASC);
* */